#include <iostream>
#include <algorithm>
#include <vector>

constexpr int MAXN = 20005;
int father[MAXN * 2];

struct Edge {
	int u, v, w;
	bool operator <(const Edge& e) const {
		return this->w > e.w;
	}
};

void Build(const int N) {
	for (int i = 1; i <= 2 * N; i++) {
		father[i] = i;
	}
}

int Find(const int x) {
	if (x != father[x]) {
		father[x] = Find(father[x]);
	}
	return father[x];
}

bool Union(const int a, const int b, const int N) {
	const int fa1 = Find(a);
	const int fa2 = Find(b);
	const int fa3 = Find(a + N);
	const int fa4 = Find(b + N);

	if (fa1 == fa2 || fa3 == fa4) {
		return false;
	}

	father[fa1] = fa4;
	father[fa3] = fa2;

	return true;

}


bool Check(const int x, const int N,
	const std::vector<Edge>& edges) {
	Build(N);

	for (const auto& [u, v, w]
		: edges) {
		if (w <= x) {
			return true;
		}

		const int a = u;
		if (const int b = v; !Union(a, b, N)) {
			return false;
		}
	}

	return true;

}

/**
 * NOIP2010 关押罪犯
 */
int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);


	int N, M;
	std::cin >> N >> M;

	std::vector<Edge> edges(M);
	for (int i = 0; i < M; i++) {
		std::cin >> edges[i].u >> edges[i].v >> edges[i].w;
	}

	std::sort(edges.begin(), edges.end());

	int l = 0;
	int r = 1e9;
	int res = 0;
	while (l <= r) {
		if (const int m = l + ((r - l) >> 1);
			Check(m, N, edges)) {
			res = m;
			r = m - 1;
		}
		else {
			l = m + 1;
		}
	}

	std::cout << res;
	return 0;
}
